package business.message;

import demo.message.RaftMessage;
import demo.message.RaftMessageHandler;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;

/**
 * 基于网络的Raft消息处理器实现
 */
public class NetworkMessageHandler implements RaftMessageHandler {

    private final Map<String, String> peerAddresses;
    private final String nodeId;  // 当前节点的ID

    public NetworkMessageHandler(String nodeId, Map<String, String> peerAddresses) {
        this.nodeId = nodeId;
        this.peerAddresses = peerAddresses;
    }

    @Override
    public RaftMessage.VoteResponse sendVoteRequest(String nodeId, RaftMessage.VoteRequest request) {
        String address = peerAddresses.get(nodeId);
        if (address == null) {
            System.err.println("未找到节点地址: " + nodeId);
            return new RaftMessage.VoteResponse(request.getTerm(), nodeId, request.getCandidateId(), false);
        }

        try {
            String url = "http://" + address + "/raft/vote";
            System.out.println("节点 " + this.nodeId + " 向节点 " + nodeId + " 发送投票请求 (地址: " + url + ")");
            
            // 创建HTTP连接
            HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestProperty("Content-Type", "application/octet-stream");
            
            // 发送请求
            try (ObjectOutputStream out = new ObjectOutputStream(conn.getOutputStream())) {
                out.writeObject(request);
                out.flush();
            }
            
            System.out.println("节点 " + nodeId + " 已发送投票请求，等待响应...");

            // 读取响应
            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                try (ObjectInputStream in = new ObjectInputStream(conn.getInputStream())) {
                    return (RaftMessage.VoteResponse) in.readObject();
                }
            } else {
                System.err.println("投票请求失败，HTTP状态码: " + conn.getResponseCode());
                return new RaftMessage.VoteResponse(request.getTerm(), nodeId, request.getCandidateId(), false);
            }
        } catch (Exception e) {
            System.err.println("发送投票请求失败: " + e.getMessage());
            e.printStackTrace();  // 添加更详细的错误信息
            return new RaftMessage.VoteResponse(request.getTerm(), nodeId, request.getCandidateId(), false);
        }
    }

    @Override
    public RaftMessage.AppendEntriesResponse sendAppendEntries(String nodeId, RaftMessage.AppendEntriesRequest request) {
        String address = peerAddresses.get(nodeId);
        if (address == null) {
            System.err.println("未找到节点地址: " + nodeId);
            return new RaftMessage.AppendEntriesResponse(request.getTerm(), nodeId, this.nodeId, false, -1);
        }

        try {
            String url = "http://" + address + "/raft/append";
            
            // 创建HTTP连接
            HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestProperty("Content-Type", "application/octet-stream");
            
            // 发送请求
            try (ObjectOutputStream out = new ObjectOutputStream(conn.getOutputStream())) {
                out.writeObject(request);
                out.flush();
            }

            // 读取响应
            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                try (ObjectInputStream in = new ObjectInputStream(conn.getInputStream())) {
                    return (RaftMessage.AppendEntriesResponse) in.readObject();
                }
            } else {
                System.err.println("附加日志请求失败，HTTP状态码: " + conn.getResponseCode());
                return new RaftMessage.AppendEntriesResponse(request.getTerm(), nodeId, this.nodeId, false, -1);
            }
        } catch (Exception e) {
            System.err.println("发送附加日志请求失败: " + e.getMessage());
            return new RaftMessage.AppendEntriesResponse(request.getTerm(), nodeId, this.nodeId, false, -1);
        }
    }
}